home *** CD-ROM | disk | FTP | other *** search
/ Just Call Me Internet / Just Call Me Internet.iso / prog / atari / m2 / cat3src / cat / listdl.i < prev    next >
Text File  |  1997-10-26  |  32KB  |  1,017 lines

  1. IMPLEMENTATION MODULE ListDl;
  2.  
  3. FROM SYSTEM     IMPORT ADDRESS, CAST, LONGWORD, CALLSYS, CADR, ADR;
  4.  
  5. FROM Storage    IMPORT ALLOCATE, DEALLOCATE;
  6.  
  7. FROM Strings    IMPORT Space, Append, Pos, Upper, Assign, DelTrailingBlanks,
  8.                        DelLeadingBlanks, StrEqual;
  9.  
  10. FROM BinOps     IMPORT LowerInt, HigherInt;
  11.  
  12. IMPORT GrafBase;
  13.  
  14. FROM MagicSys   IMPORT sBITSET, sINTEGER, lINTEGER;
  15.  
  16. IMPORT MagicAES, mtUtils, mtAppl, mtAlerts;
  17.  
  18. FROM mtDials    IMPORT DSTART, DFINISH, CSCREEN,
  19.                        DialCenter, DialDraw, DialDo, DialForm, 
  20.                        SetUserkey, GetKbdState, DialConfig, 
  21.                        InstallHandler, RemoveHandler, CallByHandling;
  22.  
  23. FROM ListUtils  IMPORT tPoint, TwoRects, WordArray, FrameRects, DiffVertRect,
  24.                        CalcAbsArea, formSetSlider;
  25.  
  26. IMPORT ListMan, RectFuncs;
  27.  
  28. IMPORT MTE;
  29.  
  30. IMPORT WinDials;
  31.  
  32. (*$H+*)
  33.  
  34.   TYPE  DIAL    = POINTER TO DialInfo;
  35.  
  36.         DialInfo    = RECORD
  37.                         (* externe Parameter *)
  38.                         tree            : ADDRESS;
  39.                         listInfo        : ListMan.LISTINFO;
  40.                         env             : ADDRESS;
  41.                         boxIndex,
  42.                         backIndex       : sINTEGER;
  43.                         okBut, 
  44.                         cancelBut       : sINTEGER;
  45.                         doubleClickBut  : sINTEGER;
  46.                         flags           : ldElemSet;
  47.                         autoEdField     : sINTEGER;
  48.                         lastSel         : lINTEGER;
  49.                         hdl             : ldHandler;
  50.                        
  51.                         (* Fr Fensterdialoge: *)
  52.                         listSetValues   : wdSetProc;
  53.                         listGetValues   : wdSetProc;
  54.                         listCheckExit   : lsCheckExitProc;
  55.                         lastElemPtr     : POINTER TO ADDRESS;
  56.                         
  57.                         listSpecials    : POINTER TO ARRAY [0..511] OF specialButHdler;
  58.                         listSpecialCount: INTEGER;
  59.                         autoEdit        : INTEGER;
  60.                         
  61.                         inLoop          : inLoopProc;
  62.                         exitBut         : INTEGER;
  63.                         initial         : BOOLEAN;
  64.                         
  65.                         next            : DIAL;
  66.                       END;
  67.  
  68.  
  69. TYPE    CharSet = SET OF CHAR;
  70.  
  71. CONST   numChars        = CharSet{'0','1'..'9'};
  72.         numSpaceChars   = CharSet{' ','0','1'..'9'};
  73.         specialChars    = CharSet{10C, '|'};
  74.  
  75. VAR 
  76.         dialList        : DIAL;
  77.         
  78.         voidO           : BOOLEAN;
  79.         voidI           : sINTEGER;
  80.         
  81.         autoDial        : DIAL;
  82.  
  83. PROCEDURE BuildLdHandler (listStart   : ADDRESS; (* Zeiger auf die Liste *)
  84.                           resetList   : ResetProc; 
  85.                           nextEntry,
  86.                           prevEntry   : MoveProc;
  87.                           listElems   : CountProc;
  88.                           isEnabled   : entryIsSelectableProc;
  89.                           selEntry    : selectEntryProc;
  90.                           entryToStr  : entryToStringProc;
  91.                           isSelected  : isSelectedProc;
  92.                           drawEntry   : drawEntryProc;
  93.                           voffset     : sINTEGER;
  94.                           vsize       : sINTEGER;
  95.                           hStep       : sINTEGER;
  96.                           maxWidth    : sINTEGER;
  97.                           VAR handler: ldHandler);
  98. (* Baut aus den bergebenen Daten einen ldHandler zusammen 
  99.  *)
  100. BEGIN
  101.   handler := ldHandler{listStart, resetList, nextEntry, prevEntry,
  102.                        listElems, isEnabled, selEntry, entryToStr, 
  103.                        isSelected, drawEntry, voffset, vsize, hStep, 
  104.                        maxWidth};
  105. END BuildLdHandler;
  106.  
  107.  
  108. PROCEDURE PrepareListDial (tree : ADDRESS;
  109.                            elems : ldElemSet;
  110.                            VAR handler : ldHandler;
  111.                            boxIndex, 
  112.                            boxBack   : sINTEGER;
  113.                            okBut, 
  114.                            cancelBut : sINTEGER;
  115.                            env       : ADDRESS;
  116.                            doubleClickButton : sINTEGER;
  117.                            VAR d : DIAL) : BOOLEAN;
  118.   (* Bereitet eine scrollbare Liste vor. 
  119.    * Dabei muž ein DialInit schon erfolgt sein.
  120.    *)
  121.   VAR   i : sINTEGER;
  122.         d2      : DIAL;
  123.         selMode : ListMan.selectMode;
  124. BEGIN
  125.   NEW (d);
  126.   IF d = NIL THEN RETURN FALSE END;
  127.   d^.next := NIL;
  128.   d^.tree       := tree;
  129.   d^.flags      := elems;
  130.   d^.hdl        := handler;
  131.   d^.inLoop     := inLoopProc(NIL);
  132.   (*
  133.   d^.resetList  := resetList;
  134.   d^.nextEntry  := nextEntry;
  135.   d^.prevEntry  := prevEntry;
  136.   d^.listElems  := listElems;
  137.   d^.selEntry   := selEntry ;
  138.   d^.isEnabled  := isEnabled;
  139.   d^.isSelected := isSelected;
  140.   *)
  141.   
  142.   d^.boxIndex   := boxIndex  ;
  143.   d^.backIndex  := boxBack   ;
  144.   d^.okBut      := okBut;
  145.   d^.cancelBut  := cancelBut;
  146.   d^.env        := env       ;
  147.   (*
  148.   d^.noSelect   := ~ select  ;
  149.   d^.multiple   := multiple  ;
  150.   d^.useArrows  := useArrows ;
  151.   d^.entryToStr := entryToStr;
  152.   d^.exitOnDoubleClick := exitOnDoubleClick;
  153.   *)
  154.   d^.doubleClickBut := doubleClickButton;
  155.   (* EXCL (d^.flags, ldAutolocate); *)
  156.   (*
  157.   d^.autoLocator:= FALSE;
  158.   *)
  159.   (* Jetzt noch ein paar Sachen initialisieren *)
  160.  
  161.   WITH d^.hdl DO
  162.     (* selMode festlegen *)
  163.     IF ~(ldSelect IN elems)
  164.     THEN
  165.       selMode := ListMan.smNone
  166.     ELSIF (ldMultiple IN elems)
  167.     THEN
  168.       selMode := ListMan.smMulti
  169.     ELSE
  170.       selMode := ListMan.smOne
  171.     END;
  172.     (* ListInfo erzeugen *)
  173.     IF ~ListMan.InitList (list, env, selEntry, isSelected, 
  174.                          isEnabled, drawEntry,                     
  175.                          resetList, nextEntry, prevEntry, listElems, selMode,
  176.                          d^.listInfo)
  177.     THEN
  178.       RETURN FALSE
  179.     END;
  180.     IF ~ListMan.SetListDialSpecs(d^.listInfo, tree, boxIndex, boxBack, voffset, 
  181.                                  vsize, hStep, maxWidth)
  182.     THEN
  183.       voidO := ListMan.FreeList (d^.listInfo);
  184.       RETURN FALSE
  185.     END;
  186.   END;
  187.   
  188.   (* Jetzt in Liste h„ngen *)
  189.   IF dialList = NIL 
  190.   THEN 
  191.     dialList := d
  192.   ELSE
  193.     d2 := dialList;
  194.     WHILE d2^.next # NIL DO
  195.       d2 := d2^.next;
  196.     END;
  197.     d2^.next := d;
  198.   END;
  199.   
  200.   WITH d^ DO
  201.     (* Selektierten Eintrag suchen! *)
  202.     ListMan.ListScroll2Selection (listInfo, FALSE);
  203.     lastSel := ListMan.ListFirstSelected (listInfo);
  204.   
  205.     IF ldArrows IN flags THEN
  206.      FOR i := 0 TO 4 DO
  207.       SetUserkey (tree, -3, 72, BITSET(i), FALSE, TRUE); (* Cursor Up *)
  208.       SetUserkey (tree, -4, 80, BITSET(i), FALSE, TRUE); (* Cursor Down *)
  209.      END;
  210.      SetUserkey (tree, -5, 71, {}, FALSE, TRUE);  (* Home *)
  211.      SetUserkey (tree, -6, 71, {1}, FALSE, TRUE); (* Shift-Home *)
  212.     END;
  213.   
  214.   END;  
  215.   (*
  216.   DialDraw (tree, 0, 999, sFrame, FALSE);
  217.   *)
  218.   RETURN TRUE
  219. END PrepareListDial;  
  220.  
  221. PROCEDURE ReleaseListDial (VAR d : DIAL) : BOOLEAN;
  222. (* gibt einen Listenhandler wieder frei. *)
  223.   VAR d2 : DIAL;
  224.       m  : sINTEGER;
  225. BEGIN
  226.   IF d = NIL THEN RETURN FALSE END;
  227.   d2 := dialList;
  228.   IF d2 = d
  229.   THEN
  230.     dialList := d^.next;
  231.   ELSE
  232.     WHILE (d2 # NIL) & (d2^.next # d) DO 
  233.       d2 := d2^.next;
  234.     END;
  235.     IF d2 = NIL
  236.     THEN RETURN FALSE
  237.     END;
  238.     (* d aush„ngen *)
  239.     d2^.next := d^.next;
  240.   END;
  241.   (* ListMan freigeben *)
  242.   voidO := ListMan.FreeList (d^.listInfo);
  243.   IF ldArrows IN d^.flags
  244.   THEN
  245.     (* Userkeys wieder austragen *)
  246.     FOR m := 0 TO 4 DO
  247.       SetUserkey (d^.tree, -3, 72, BITSET(m), FALSE, FALSE); (* Cursor Up *)
  248.       SetUserkey (d^.tree, -4, 80, BITSET(m), FALSE, FALSE); (* Cursor Down *)
  249.     END;
  250.     SetUserkey (d^.tree, -5, 71, {},  FALSE, FALSE); (* Home *)
  251.     SetUserkey (d^.tree, -6, 71, {1}, FALSE, FALSE); (* Shift-Home *)
  252.   END;
  253.   DISPOSE (d);
  254.   RETURN TRUE
  255. END ReleaseListDial;
  256.  
  257. PROCEDURE NilDIAL () : DIAL;
  258. BEGIN
  259.   RETURN NIL
  260. END NilDIAL;
  261.  
  262. PROCEDURE FindDial (findTree : ADDRESS; button : sINTEGER; treeOnly : BOOLEAN) : DIAL;
  263. (* Gibt den zu dem Tree und dem Button geh”renden DIAL zurck,
  264.  * ansonsten NIL.
  265.  * Wenn der Button < 0 ist, wird nur nach dem Tree gesucht.
  266.  *)
  267.  VAR d : DIAL;
  268.      but : sINTEGER;
  269.      found : BOOLEAN;
  270.      useArrows: BOOLEAN;
  271. BEGIN
  272.   d := dialList;
  273.   but := INTEGER (BITSET(button)-{15});
  274.   WHILE d # NIL DO
  275.     WITH d^ DO 
  276.       useArrows := ldArrows IN flags;
  277.       IF tree=findTree 
  278.       THEN 
  279.         found := TRUE;
  280.       ELSE 
  281.         found := FALSE;
  282.       END;
  283.       IF treeOnly & found
  284.       THEN
  285.         RETURN d
  286.       ELSIF ~treeOnly & 
  287.          found & 
  288.          (
  289.          (but = boxIndex) OR
  290.          (but = backIndex ) OR
  291.          (button = -1) OR               (* Undo *)
  292.          ((button = -3) & useArrows) OR (* Arrow 1 *)
  293.          ((button = -4) & useArrows) OR (* Arrow 2 *)
  294.          ((button = -5) & useArrows) OR (* Home *)
  295.          ((button = -6) & useArrows) OR (* Shift-Home *)
  296.          (but = okBut) OR
  297.          (but = cancelBut))
  298.       THEN
  299.         found := TRUE;
  300.       ELSE
  301.         found := FALSE;
  302.       END;
  303.       IF found THEN RETURN d END;
  304.     END;
  305.     d := d^.next;
  306.   END;
  307.   d := NIL;
  308.   RETURN d
  309. END FindDial;
  310.  
  311. PROCEDURE InitAutoLocator (d: DIAL);
  312. BEGIN
  313.   autoDial := d;
  314. END InitAutoLocator;
  315.  
  316. PROCEDURE FreeAutoLocator ();
  317. BEGIN
  318.   autoDial := NIL;
  319. END FreeAutoLocator;
  320.  
  321. PROCEDURE AutoLocate (tree : ADDRESS; mx, my : sINTEGER; scan : sINTEGER;
  322.                       kstate : sBITSET; event : sBITSET; edObj : sINTEGER): sBITSET;
  323.   VAR i        : sINTEGER;
  324.       idx      : lINTEGER;
  325.       pt,
  326.       ptx      : ADDRESS;
  327.       d        : DIAL;
  328.       search,
  329.       lastStr,
  330.       str       : ARRAY [0..255] OF CHAR;
  331.       sFrame    : mtUtils.tRect;
  332.       halfSize  : INTEGER;
  333.       voidO     : BOOLEAN;
  334. BEGIN
  335.   IF ~(MagicAES.MUKEYBD IN event) THEN RETURN {} END;  (* Ist uns egal *)
  336.   (* Cursortasten, Funktionstasten und noch ein paar Sondertasten abfangen *)
  337.   IF ((scan >=59) & (scan <= 72)) OR (scan = 75) OR (scan = 77) OR
  338.      ((scan >= 80) & (scan <= 98)) OR (scan = 42) OR (scan=54) OR (scan=71)
  339.   THEN RETURN {} END;
  340.   (* So, jetzt ist das also fr uns interessant! *)
  341.   IF autoDial = NIL
  342.   THEN
  343.     (* Dial suchen *)
  344.     d := FindDial (tree, -1, TRUE);
  345.     IF d = NIL THEN RETURN {} END;
  346.   ELSE
  347.     d := autoDial
  348.   END;
  349.   (* Jetzt suchen *)
  350.   WITH d^ DO
  351.     (* Test auf Namecompletion *)
  352.     autoEdField := edObj;
  353.     IF autoEdField >= 0
  354.     THEN
  355.       (* String aus Editfeld holen *)
  356.       mtUtils.ObjcString (tree, edObj, search);
  357.       Upper (search);
  358.       DelLeadingBlanks (search);
  359.     ELSE
  360.       (* Nur Taste auswerten *)
  361.       search[0] := CAP(mtUtils.CharCode (scan, kstate));
  362.       search[1] := 0C;
  363.     END;
  364.     (* ListBox an aktuelle Koordinaten anpassen *)
  365.     IF (scan = 15) (* TAB *) & (autoEdField >= 0)
  366.     THEN
  367.       lastStr[0] := '';
  368.       hdl.resetList (hdl.list);
  369.       (* Namen komplettieren *)
  370.       REPEAT 
  371.         ptx := hdl.nextEntry (hdl.list);
  372.         IF ptx # NIL
  373.         THEN
  374.           hdl.entryToStr (ptx, env, str);
  375.           Upper (str);
  376.           DelLeadingBlanks (str);
  377.           IF hdl.isEnabled (ptx, env) & (Pos (search, str, 0) = 0)
  378.           THEN
  379.             (* Ist enthalten, also merken *)
  380.             IF lastStr[0] # ''
  381.             THEN
  382.               (* vergleichen mit letztem, bis der erste Unterschied auftritt *)
  383.               i := 0;
  384.               WHILE (CAP(str[i]) = CAP(lastStr[i])) & (i < INTEGER(LENGTH(lastStr))) DO INC (i) END;
  385.               hdl.entryToStr (ptx, env, lastStr);
  386.               lastStr[i] := 0C;
  387.             ELSE
  388.               hdl.entryToStr (ptx, env, lastStr);
  389.             END;
  390.           END;
  391.         END;
  392.       UNTIL ptx = NIL;
  393.       IF lastStr[0] # ''
  394.       THEN
  395.         DelTrailingBlanks (lastStr);
  396.         (*
  397.         i := INTEGER(LENGTH(lastStr))-1;
  398.         WHILE (i > 0) & ~(lastStr[i] IN specialChars) DO DEC (i); END;
  399.         IF lastStr[i] IN specialChars THEN lastStr[i] := 0C; END;
  400.         DelTrailingBlanks (lastStr);
  401.         i := INTEGER(LENGTH(lastStr))-1;
  402.         WHILE (i > 0) & (lastStr[i] IN numChars) & (lastStr[i-1] IN numSpaceChars) DO lastStr[i] := 0C; DEC(i); END;
  403.         (* Namen in Editfeld setzen und neu zeichnen *)
  404.         DelTrailingBlanks (lastStr);
  405.         *)
  406.         mtUtils.SetObjcString (tree, edObj, lastStr);
  407.         WinDials.WinEditChanged (tree, edObj);
  408.         RETURN {1};
  409.       ELSE
  410.         RETURN {}
  411.       END;
  412.     ELSE
  413.       hdl.resetList (hdl.list);
  414.       idx := 0;
  415.       REPEAT 
  416.         ptx := hdl.nextEntry (hdl.list);
  417.         INC (idx);
  418.         IF ptx # NIL
  419.         THEN
  420.           hdl.entryToStr (ptx, env, str);
  421.           Upper (str);
  422.           DelLeadingBlanks (str);
  423.           IF hdl.isEnabled (ptx, env) & (Pos (search, str, 0) = 0)
  424.           THEN
  425.             (* Jetzt auch darstellen *)
  426.             ListMan.ListInvertEntry (listInfo, idx);
  427.             lastSel := idx;
  428.             IF ADDRESS(d^.inLoop) # NIL
  429.             THEN 
  430.               d^.inLoop (ptx, env);
  431.             END;
  432.             RETURN {}
  433.           END;
  434.         END;
  435.       UNTIL ptx = NIL;
  436.       (* Nichts gefunden, alten Eintrag deselektieren *)
  437.       IF lastSel > 0 THEN ListMan.ListDeselEntry (listInfo, lastSel); END;
  438.       lastSel := -1;
  439.       IF ADDRESS(d^.inLoop) # NIL
  440.       THEN 
  441.         d^.inLoop (ptx, env);
  442.       END;
  443.     END;
  444.   END;
  445.   RETURN {};
  446. END AutoLocate;
  447.  
  448.  
  449. PROCEDURE HandleListDial (d : DIAL; 
  450.                           VAR but : sINTEGER;     (* Der von DialDo gelieferte Button *)
  451.                           mx, my  : sINTEGER;     (* Die Mauskoordinaten *)
  452.                           kState  : BITSET;     (* Der Tastaturstatus  *)
  453.                       VAR lastElem : ADDRESS) : BOOLEAN; 
  454. (* Verwaltet die Events, wenn etwas in diesem Dial angeklickt wurde 
  455.  *)
  456.  
  457.  VAR sFrame : mtUtils.tRect;
  458.      doubleClick : BOOLEAN;
  459.      button : BITSET;
  460.      i      : sINTEGER;
  461.      clicks : sINTEGER;
  462.      selLast: lINTEGER;
  463.      noSelect: BOOLEAN;
  464.      multiple: BOOLEAN;
  465.      oldLast: lINTEGER;
  466.  
  467. BEGIN
  468.   WITH d^ DO 
  469.     noSelect := ~(ldSelect IN flags);
  470.     multiple := ldMultiple IN flags;
  471.     oldLast := lastSel;
  472.     IF but = -1 (* Userproc *) THEN
  473.       (* Redraw von edObj *)
  474.       WinDials.WinDialDraw (tree, autoEdField, 0, sFrame, FALSE);
  475.       RETURN FALSE;
  476.     (*
  477.       IF ldAutolocate IN flags
  478.       THEN
  479.         (* Redraw von edObj *)
  480.         DialDraw (tree, autoEdField, 0, sFrame, FALSE);
  481.         RETURN FALSE;
  482.       ELSE
  483.         but := cancelBut;
  484.         mtUtils.InclState (tree, but, MagicAES.SELECTED);
  485.         DialDraw (tree, but, 0, sFrame, FALSE);
  486.         RETURN TRUE
  487.       END;
  488.     *)
  489.     END;
  490.     IF initial & (but < 0)
  491.     THEN
  492.       RETURN FALSE;
  493.     END;
  494.     IF but = -3      (* Cursor Up *)
  495.     THEN
  496.       IF (2 IN kState) OR noSelect OR multiple
  497.       THEN
  498.         (* Ctrl *)
  499.         IF (0 IN kState) OR (1 IN kState)
  500.         THEN 
  501.           (* Ctrl-Shift *)
  502.           ListMan.ListPgUp (listInfo);
  503.         ELSE
  504.           ListMan.ListLnUp (listInfo);
  505.         END;
  506.       ELSE
  507.         IF (0 IN kState) OR (1 IN kState)
  508.         THEN
  509.           (* Shift + Control *)
  510.           lastSel := ListMan.ListSelPgUp (listInfo);
  511.         ELSE
  512.           lastSel := ListMan.ListSelUp (listInfo);
  513.         END;
  514.       END;
  515.     ELSIF (but = -4) (* Cursor Down *)
  516.     THEN
  517.       IF (2 IN kState) OR noSelect OR multiple
  518.       THEN
  519.         (* ctrl: Scrollen *)
  520.         IF (0 IN kState) OR (1 IN kState)
  521.         THEN
  522.           (* Shift *)
  523.           ListMan.ListPgDown (listInfo);
  524.         ELSE
  525.           ListMan.ListLnDown (listInfo);
  526.         END;
  527.       ELSE
  528.         (* Selected Entry Down   *)
  529.         IF (0 IN kState) OR (1 IN kState)
  530.         THEN
  531.           lastSel := ListMan.ListSelPgDown (listInfo);
  532.         ELSE
  533.           lastSel := ListMan.ListSelDown (listInfo);
  534.         END;
  535.       END;
  536.     ELSIF but = -5
  537.     THEN
  538.       (* Home: Nach oben gehen *)
  539.       IF noSelect OR multiple
  540.       THEN
  541.         ListMan.ListFirst (listInfo);
  542.       ELSE
  543.         lastSel := ListMan.ListSelFirst (listInfo);
  544.       END;
  545.     ELSIF but = -6
  546.     THEN
  547.       (* Shift-Home: Ans Ende gehen *)
  548.       IF noSelect OR multiple
  549.       THEN
  550.         ListMan.ListLast (listInfo);
  551.       ELSE
  552.         lastSel := ListMan.ListSelLast (listInfo);
  553.       END;
  554.     END;
  555.     lastElem := ListMan.ListFindEntry (listInfo, lastSel);
  556.     IF lastSel # oldLast
  557.     THEN
  558.       WinDials.WinEditChanged (tree, -1);
  559.     END;
  560.     doubleClick := but # (INTEGER (BITSET(but)-{15}));
  561.     but := INTEGER(BITSET(but)-{15});
  562.     IF but >= 0
  563.     THEN
  564.       IF (but = okBut) OR (but = cancelBut)
  565.       THEN
  566.         RETURN TRUE
  567.       ELSIF (but = boxIndex) OR (but = backIndex)
  568.       THEN
  569.         clicks := 1;
  570.         IF doubleClick THEN INC (clicks) END;
  571.         selLast := ListMan.ListClick (listInfo, mx, my, kState, clicks);
  572.         IF selLast >= 0
  573.         THEN
  574.           lastSel := selLast;
  575.           WinDials.WinEditChanged (tree, -1);
  576.         END;
  577.         lastElem := ListMan.ListFindEntry (listInfo, lastSel);
  578.         IF doubleClick & (ldDoubleExit IN flags) & (lastElem # NIL)
  579.          & (but = boxIndex)
  580.         THEN
  581.           IF ADDRESS(d^.inLoop) # NIL
  582.           THEN 
  583.             d^.inLoop (d^.lastElemPtr^, d^.env);
  584.           END;
  585.           IF ~mtUtils.InState (tree, doubleClickBut, MagicAES.DISABLED)
  586.             & mtUtils.InFlag (tree, doubleClickBut, MagicAES.SELECTABLE)
  587.           THEN
  588.             but := doubleClickBut;
  589.             mtUtils.InclState (tree, but, MagicAES.SELECTED);
  590.             WinDials.WinDialDraw (tree, but, 0, sFrame, FALSE);
  591.             RETURN (but = okBut) OR (but = cancelBut);
  592.           END;
  593.         END;
  594.       END;
  595.     END; (* IF but *)
  596.   END (* WITH d^ DO *);
  597.   RETURN FALSE; 
  598. END HandleListDial;
  599.  
  600. PROCEDURE dummyInLoop (entry, env : ADDRESS);
  601. (* Dummy-Prozedur als InLoopProc *)
  602. END dummyInLoop;
  603.  
  604. PROCEDURE dummyCheckExit (entry, env : ADDRESS; button: INTEGER; 
  605.                           lastSel: ADDRESS; kstate: BITSET): BOOLEAN;
  606. (* Dummy-Prozedur fr Exitcheck, gibt immer TRUE zurck *)
  607. BEGIN
  608.   RETURN TRUE;
  609. END dummyCheckExit;
  610.  
  611.  
  612. PROCEDURE DrawListDial (d: DIAL; clip: GrafBase.Rectangle);
  613. (* Zeichnet die Liste komplett inklusive aller Elemente *)
  614.   VAR upperFrame : GrafBase.Rectangle;
  615. BEGIN
  616.   IF d # NIL
  617.   THEN
  618.     WITH d^ DO
  619.       initial := FALSE;
  620.       mtUtils.CalcArea (tree, backIndex, upperFrame);
  621.       ListMan.DrawList (listInfo, RectFuncs.ClipRect (upperFrame, clip));
  622.     END;
  623.   END;
  624. END DrawListDial;
  625.  
  626. PROCEDURE doListDial (tree : ADDRESS;
  627.                       elems : ldElemSet;
  628.                       VAR handler : ldHandler;
  629.                       boxIndex, boxBack,
  630.                       okBut, cancelBut : sINTEGER;
  631.                       env      : ADDRESS;
  632.                       doubleClickButton : sINTEGER;
  633.                       autoEdit   : INTEGER;
  634.                       inLoop     : inLoopProc;
  635.                       specials   : ARRAY OF specialButHdler;
  636.                       setValues  : wdSetProc;
  637.                       getValues  : wdSetProc;
  638.                       VAR lastElem : ADDRESS) : sINTEGER;
  639.  
  640. (* Handelt eine komplette Scrollbare Liste.
  641.  * Gibt den Index des Exit-Buttons zurck.
  642.  * In lastElem wird die Adresse des zuletzt selektierten Elements zurckgegeben.
  643.  * Bei multiple = TRUE k”nnen mehrere Eintr„ge selektiert werden.
  644.  *)
  645.  
  646.   VAR org, space : mtUtils.tRect;
  647.  
  648.       but        : sINTEGER;
  649.       buts       : BITSET;
  650.       kstate     : BITSET;
  651.       draw,
  652.       exit       : BOOLEAN;
  653.       d          : DIAL;
  654.       d2         : DIAL;
  655.       upperFrame,
  656.       lowerFrame : GrafBase.Rectangle;
  657.       mx,
  658.       my         : sINTEGER;
  659.       i          : sINTEGER;
  660.       pt         : ADDRESS;
  661.       str, str2  : ARRAY [0..255] OF CHAR;
  662.  
  663. BEGIN
  664.         (* no grow & shrink boxes *)
  665.   org.w := -1;
  666.  
  667.   IF ldAutolocate IN elems
  668.   THEN
  669.     InstallHandler (tree, AutoLocate, CallByHandling, 0, 0, upperFrame, NIL);
  670.   END;
  671.  
  672.   DialCenter (tree, CSCREEN, 0, 0, upperFrame);
  673.   DialForm (tree, DSTART, upperFrame, lowerFrame);
  674.   
  675.   IF ~ PrepareListDial (tree, elems,
  676.                         handler, 
  677.                         boxIndex, boxBack,
  678.                         okBut, cancelBut,
  679.                         env, doubleClickButton,
  680.                         d)
  681.   THEN 
  682.     lastElem := NIL;   
  683.     DialForm (tree, DFINISH, upperFrame, lowerFrame);
  684.     RETURN cancelBut 
  685.   END;
  686.   MagicAES.WindUpdate (MagicAES.BEGUPDATE);
  687.   MagicAES.WindUpdate (MagicAES.BEGMCTRL);
  688.   DialDraw (tree, 0, 999, upperFrame, FALSE);
  689.   mtUtils.CalcArea (tree, boxBack, upperFrame);
  690.   ListMan.DrawList (d^.listInfo, upperFrame);
  691.   IF ldAutolocate IN elems
  692.   THEN
  693.     buts := AutoLocate (tree, 0, 0, 0, {}, {MagicAES.MUKEYBD}, autoEdit);
  694.   ELSE 
  695.   END;
  696.   mtAppl.MouseArrow();
  697.   LOOP
  698.     IF inLoop # inLoopProc(NIL) THEN
  699.       inLoop (lastElem, env);      (* inLoopProc aufrufen *)
  700.     END;
  701.     
  702.     but := DialDo (tree, 0);
  703.     MagicAES.GrafMkstate (mx, my, buts, kstate);
  704.     kstate := GetKbdState();
  705.     
  706.     d2 := FindDial (tree, but, FALSE);
  707.     IF d2 # NIL
  708.     THEN
  709.       IF HandleListDial  (d2, but, mx, my, kstate, lastElem) THEN EXIT END;
  710.     END;
  711.     IF inLoop # inLoopProc(NIL) THEN
  712.       inLoop (lastElem, env);      (* inLoopProc aufrufen *)
  713.     END;
  714.  
  715.     (* specials *)
  716.     but := INTEGER(BITSET(but)-{15});
  717.     FOR i := 0 TO INTEGER(HIGH (specials)) DO
  718.       IF (but = specials[i].objc)
  719.        & ~mtUtils.InState (tree, specials[i].objc, MagicAES.DISABLED)
  720.        &  mtUtils.InFlag (tree, specials[i].objc, MagicAES.SELECTABLE)
  721.       THEN
  722.         specials[i].proc (but, env, ADDRESS(d^.listInfo), draw, exit);
  723.         IF draw THEN
  724.           mtUtils.CalcArea (tree, boxBack, upperFrame);
  725.           ListMan.DrawList (d^.listInfo, upperFrame);
  726.           IF ldAutolocate IN elems
  727.           THEN
  728.             buts := AutoLocate (tree, 0, 0, 0, {}, {MagicAES.MUKEYBD}, autoEdit);
  729.           END;
  730.           d^.lastSel := ListMan.ListFirstSelected (d^.listInfo);
  731.         END;
  732.         IF exit THEN EXIT END;
  733.       END;
  734.     END; (* FOR i *)
  735.   END (* LOOP *);
  736.   kstate := GetKbdState();
  737.   IF (ldAutolocate IN elems) & (d^.lastSel # -1) & (autoEdit >= 0)
  738.   THEN 
  739.     WITH d^ DO
  740.       (* Ein Eintrag ist selektiert und der Dialog wurde nicht mit Shift-xxx verlassen *)
  741.       lastElem := ListMan.ListFindEntry (listInfo, lastSel);
  742.       (* String noch setzen *)
  743.       IF lastElem # NIL
  744.       THEN
  745.         hdl.entryToStr (lastElem, env, str);
  746.         IF ~((0 IN kstate) OR (1 IN kstate))
  747.         THEN
  748.           mtUtils.SetObjcString (tree, autoEdit, str);
  749.         ELSE
  750.           (* Vergleichen, ob der String im Editfeld und der von dem 
  751.            * selektierten Eintrag gleich sind
  752.            *)
  753.           mtUtils.ObjcString (tree, autoEdit, str2);
  754.           IF ~StrEqual (str2, str)
  755.           THEN
  756.             lastElem := NIL
  757.           END;
  758.         END;
  759.       END;
  760.     END;
  761.   END;
  762.   mtUtils.ExclState (tree, but, MagicAES.SELECTED);
  763.   IF ReleaseListDial (d) THEN END;
  764.   DialForm (tree, DFINISH, upperFrame, lowerFrame);
  765.   RemoveHandler (tree);
  766.   MagicAES.WindUpdate (MagicAES.ENDMCTRL);
  767.   MagicAES.WindUpdate (MagicAES.ENDUPDATE);
  768.   RETURN but
  769. END doListDial;
  770.  
  771. PROCEDURE listSetGetValues (tree: ADDRESS; private: ADDRESS; set: BOOLEAN; exitBut: INTEGER);
  772.   VAR d: DIAL;
  773.       pt         : ADDRESS;
  774.       str, str2  : ARRAY [0..255] OF CHAR;
  775.       kstate     : BITSET;
  776.       i          : INTEGER;
  777. BEGIN
  778.   d := private;
  779.   IF set
  780.   THEN
  781.     (* Userkeys setzen *)
  782.     IF ldArrows IN d^.flags THEN
  783.      FOR i := 0 TO 4 DO
  784.       SetUserkey (tree, -3, 72, BITSET(i), FALSE, TRUE); (* Cursor Up *)
  785.       SetUserkey (tree, -4, 80, BITSET(i), FALSE, TRUE); (* Cursor Down *)
  786.      END;
  787.      SetUserkey (tree, -5, 71, {}, FALSE, TRUE);  (* Home *)
  788.      SetUserkey (tree, -6, 71, {1}, FALSE, TRUE); (* Shift-Home *)
  789.     END;
  790.   
  791.     (* Wird am Anfang aufgerufen *)
  792.     d^.listSetValues (tree, d^.env, set, exitBut);
  793.     
  794.   ELSE
  795.     (* Get wird nur am Ende aufgerufen, wir k”nnen jetzt den DIAL freigeben *)
  796.     d^.listGetValues (tree, d^.env, set, d^.exitBut);
  797.     (* Jetzt unseren Kram freigeben *)
  798.   
  799.     kstate := GetKbdState();
  800.     IF (ldAutolocate IN d^.flags) & (d^.lastSel # -1) & (d^.autoEdit >= 0)
  801.     THEN 
  802.       WITH d^ DO
  803.         (* Ein Eintrag ist selektiert und der Dialog wurde nicht mit Shift-xxx verlassen *)
  804.         d^.lastElemPtr^ := ListMan.ListFindEntry (d^.listInfo, d^.lastSel);
  805.         (* String noch setzen *)
  806.         IF d^.lastElemPtr^ # NIL
  807.         THEN
  808.           hdl.entryToStr (d^.lastElemPtr^, d^.env, str);
  809.           IF ~((0 IN kstate) OR (1 IN kstate))
  810.           THEN
  811.             mtUtils.SetObjcString (tree, d^.autoEdit, str);
  812.           ELSE
  813.             (* Vergleichen, ob der String im Editfeld und der von dem 
  814.              * selektierten Eintrag gleich sind
  815.              *)
  816.             mtUtils.ObjcString (tree, d^.autoEdit, str2);
  817.             IF ~StrEqual (str2, str)
  818.             THEN
  819.               d^.lastElemPtr^ := NIL
  820.             END;
  821.           END;
  822.         END;
  823.       END;
  824.     END;
  825.     mtUtils.ExclState (tree, d^.exitBut, MagicAES.SELECTED);
  826.     IF ReleaseListDial (d) THEN END;
  827.     RemoveHandler (tree);
  828.   END;
  829. END listSetGetValues;
  830.  
  831. PROCEDURE listDraw (tree: ADDRESS; private: ADDRESS; clip: GrafBase.Rectangle);
  832.   VAR d: DIAL;
  833.       bset: BITSET;
  834. BEGIN
  835.   d := private;
  836.   WITH d^ DO
  837.     ListMan.DrawList (listInfo, clip);
  838.     IF initial 
  839.     THEN
  840.       initial := FALSE;
  841.       (* Autolocator ggf. aufrufen *)
  842.       IF (ldAutolocate IN d^.flags)
  843.       THEN
  844.         bset := AutoLocate (tree, 0, 0, 0, {}, {MagicAES.MUKEYBD}, d^.autoEdit);
  845.       END;
  846.     END;
  847.   END;
  848. END listDraw;
  849.  
  850. PROCEDURE listButton (tree: ADDRESS; private: ADDRESS; button: INTEGER;
  851.                       mx, my : INTEGER; kstate: BITSET; clicks: INTEGER): BOOLEAN;
  852.   VAR d, d2     : DIAL;
  853.       draw,
  854.       exit      : BOOLEAN;
  855.       i         : INTEGER;
  856.       buts      : BITSET;
  857.       upperFrame: GrafBase.Rectangle;
  858. BEGIN
  859.   d := DIAL(private);
  860.   IF ADDRESS(d^.inLoop) # NIL
  861.   THEN 
  862.     d^.inLoop (d^.lastElemPtr^, d^.env);
  863.   END;
  864.             
  865.   d2 := FindDial (tree, button, FALSE);
  866.   IF d2 # NIL
  867.   THEN
  868.     IF HandleListDial  (d2, button, mx, my, kstate, d^.lastElemPtr^) 
  869.     THEN 
  870.       (* Exit gewnscht *)
  871.       IF ADDRESS(d^.inLoop) # NIL
  872.       THEN 
  873.         d^.inLoop (d^.lastElemPtr^, d^.env);
  874.       END;
  875.       d^.exitBut := button;
  876.       RETURN d^.listCheckExit (tree, d^.env, button, d^.lastElemPtr^, kstate);
  877.     END;
  878.     IF ADDRESS(d^.inLoop) # NIL
  879.     THEN 
  880.       d^.inLoop (d^.lastElemPtr^, d^.env);
  881.     END;
  882.   END;
  883.   (* specials *)
  884.   button := INTEGER(BITSET(button)-{15});
  885.   FOR i := 0 TO d^.listSpecialCount-1 DO
  886.     IF (button = d^.listSpecials^[i].objc)
  887.     & ~mtUtils.InState (tree, d^.listSpecials^[i].objc, MagicAES.DISABLED)
  888.     (* &  mtUtils.InFlag (tree, d^.listSpecials^[i].objc, MagicAES.SELECTABLE) *)
  889.     THEN
  890.       d^.listSpecials^[i].proc (button, d^.env, ADDRESS(d^.listInfo), draw, exit);
  891.       IF draw THEN
  892.         mtUtils.CalcArea (tree, d^.backIndex, upperFrame);
  893.         ListMan.DrawList (d^.listInfo, upperFrame);
  894.         IF ldAutolocate IN d^.flags
  895.         THEN
  896.           buts := AutoLocate (tree, 0, 0, 0, {}, {MagicAES.MUKEYBD}, d^.autoEdit);
  897.         END;
  898.         d^.lastSel := ListMan.ListFirstSelected (d^.listInfo);
  899.       END;
  900.       IF exit THEN 
  901.         (* Eventuell rausgehen, wenn Validierung erfolgreich *)
  902.         d^.exitBut := button;
  903.         IF ADDRESS(d^.inLoop) # NIL
  904.         THEN 
  905.           d^.inLoop (d^.lastElemPtr^, d^.env);
  906.         END;
  907.         RETURN d^.listCheckExit (tree, d^.env, button, d^.lastElemPtr^, kstate);
  908.       END;
  909.     ELSIF button = d^.listSpecials^[i].objc
  910.     THEN
  911.       (* Kann hier nur ankommen, wenn der Button disabled ist *)
  912.       mtUtils.ExclState (tree, button, MagicAES.SELECTED);
  913.       WinDials.WinDialDraw (tree, button, 0, upperFrame, FALSE);
  914.     END;
  915.   END; (* FOR i *)
  916.   IF ADDRESS(d^.inLoop) # NIL
  917.   THEN 
  918.     d^.inLoop (d^.lastElemPtr^, d^.env);
  919.   END;
  920.   RETURN FALSE;
  921. END listButton;
  922.  
  923.  
  924. PROCEDURE WinListDial (tree : ADDRESS;
  925.                         elems : ldElemSet;
  926.                         VAR handler : ldHandler;
  927.                         boxIndex, boxBack,
  928.                         okBut, cancelBut : sINTEGER;
  929.                         env      : ADDRESS;
  930.                         doubleClickButton : sINTEGER;
  931.                         autoEdit   : INTEGER;
  932.                         inLoop     : inLoopProc;
  933.                         VAR specials: ARRAY OF specialButHdler;
  934.                         specialCount: INTEGER;
  935.                         checkExit  : lsCheckExitProc;
  936.                         setValues  : wdSetProc;
  937.                         getValues  : wdSetProc;
  938.                         VAR lastElem : ADDRESS) : BOOLEAN;
  939.  
  940. (* Handelt eine komplette Scrollbare Liste.
  941.  * Gibt den Index des Exit-Buttons zurck.
  942.  * In lastElem wird die Adresse des zuletzt selektierten Elements zurckgegeben.
  943.  * Bei multiple = TRUE k”nnen mehrere Eintr„ge selektiert werden.
  944.  *)
  945.  
  946.   VAR org, space : mtUtils.tRect;
  947.  
  948.       but        : sINTEGER;
  949.       buts       : BITSET;
  950.       kstate     : BITSET;
  951.       draw,
  952.       exit       : BOOLEAN;
  953.       d          : DIAL;
  954.       d2         : DIAL;
  955.       upperFrame,
  956.       lowerFrame : GrafBase.Rectangle;
  957.       mx,
  958.       my         : sINTEGER;
  959.       i          : sINTEGER;
  960.       pt         : ADDRESS;
  961.       str, str2  : ARRAY [0..255] OF CHAR;
  962.  
  963. BEGIN
  964.         (* no grow & shrink boxes *)
  965.   org.w := -1;
  966.  
  967.   IF ~ PrepareListDial (tree, elems,
  968.                         handler, 
  969.                         boxIndex, boxBack,
  970.                         okBut, cancelBut,
  971.                         env, doubleClickButton,
  972.                         d)
  973.   THEN 
  974.     lastElem := NIL;
  975.     MTE.noMemAlert();
  976.     RETURN FALSE;
  977.   END;
  978.   d^.listSetValues := setValues;
  979.   d^.listGetValues := getValues;
  980.   d^.listCheckExit := checkExit;
  981.   d^.lastElemPtr := ADR (lastElem);
  982.   d^.listSpecials := ADR (specials);
  983.   d^.listSpecialCount := specialCount;
  984.   d^.autoEdit := autoEdit;
  985.   d^.inLoop   := inLoop;
  986.   d^.initial  := TRUE;
  987.   
  988.   IF ~WinDials.OpenWinDial (tree, ldModal IN elems, listSetGetValues, listSetGetValues, listButton,
  989.                             listDraw, "", d)
  990.   THEN
  991.     voidO := ReleaseListDial (d);
  992.     lastElem := NIL;
  993.  
  994.     MTE.info (MTE.NoWinDial);
  995.     
  996.     RETURN FALSE;
  997.   END;
  998.  
  999.   IF ldAutolocate IN elems
  1000.   THEN
  1001.     InstallHandler (tree, AutoLocate, CallByHandling, 0, 0, upperFrame, NIL);
  1002.   END;
  1003.   
  1004.   IF ldModal IN elems
  1005.   THEN
  1006.     WinDials.WinDialHandleEvents ();
  1007.   END;
  1008.  
  1009.   RETURN TRUE;
  1010. END WinListDial;
  1011.  
  1012. BEGIN
  1013.   dialList := NIL;
  1014.   autoDial     := NIL;
  1015. END ListDl.
  1016.  
  1017.